/*
 * cli_parse.c
 *
 *  Created on: 2012. 4. 8.
 *      Author: jphong
 */

#include	<ctype.h>
#include	"unp.h"
#include	"debug.h"
#include	"chat.h"
#include	"cli_parse.h"

// User Commands and help
static Cmd userCmd[] =
		{ { U_WHO, "who", "who\t-- who are logged in" },
				{ U_TALK, "talk",
						"talk [<[peer>|all]\t-- start talk session with <peer> or with all the loggined users" },
				{ U_QUIT, "quit", "quit\t-- quit session" },
				{ U_USER, "user", "user <user ID>\t-- loggin with <user ID>}" },
				{ U_DEBUG, "debug", "debug\t-- debug mode on or off (toggle)" },
				{ U_HELP, "help", "help\t-- show usage" },
				{ U_EOT, ".", ".\t-- end of talk session" }, // End of talk
				{ U_DELAY, "delay",
						"delay\t-- enforce 3 sec delay before sending request message. (toggle)" },
				///////////////////////////////////
				{ U_SEND, "send",
						"send <file name> from <sender ID> to <receiver ID>\t sender's request message: sender(client)->server" },
				{ U_ACCEPT, "accept",
						"accept <file name> from <sender ID> to <receiver ID>\t receiver's request message: receiver(client)->server" },
				{ U_REJECT, "reject",
						"reject <file name> from <sender ID> to <receiver ID>\t receiver's request message: receiver(client)->server" },
				//////////////////////////////
				{ 0, "", "" } // End of User Command List
		};

/*
 *  Classify commands into token, using cmd[] definition
 */
static int cmdType(Cmd cmd[], char *word) {
	int i;

	for (i = 0; cmd[i].token; i++) {
		if (!strcmp(word, cmd[i].str))
			return (cmd[i].token);
	}
	return (UNKNOWN);
}

/*
 * Get format for a command token
 */
static char *
getFmt(Cmd cmd[], int token) {
	int i;

	for (i = 0; cmd[i].token; i++)
		if (cmd[i].token == token)
			return (cmd[i].fmt);
	return (NULL);
}
/* Print help message
 * 	- help message for all commands if 'cmd' == 0
 * 	- help message for a command if cmd > 0
 */
static void printUsage(int cmd) {
	int i;

	for (i = 0; userCmd[i].token; i++)
		if ((cmd == 0) || (cmd && userCmd[i].token == cmd))
			printf("%s\n", userCmd[i].fmt);
}

static int debugMode = 0;

static char peerList[MAXID];
static char userID[MAXID]; // Verified user ID

static int talking;

static char prompt[MAXID];
static int delayMode;


int isDelayMode() {
	return (delayMode);
}

void delay(unsigned int sec) {
	if (delayMode)
		sleep(sec);
}

char *setPrompt(const char *str) {
	if (str != NULL) {
		strcpy(prompt, str);
		strcat(prompt, "> ");
	} else
		strcpy(prompt, "> ");

	return (prompt);
}

char *getPrompt() {
	return (prompt);
}

/* Parse a user command line and generate the corresponding request method
 *  cmdLine: string terminated with LF
 * 	Returns:  1	if requestMsg is successful generation
 * 			  0	if locally effective commands. No requestMsg geneation
 * 			 -1 if syntax error
 */

int ui_parse(char *cmdLine, char *requestMsg) {
	int cmd;
	char cmdStr[MAXID], arg[MAXID], temp1[MAXID], temp_from[MAXID], temp2[MAXID], temp_to[MAXID];
	int nword;

	// Parse the User commands
	if ((nword = sscanf(cmdLine, "%s %s %s %s %s %s ", cmdStr, arg, temp1, temp_from, temp2, temp_to)) == 0)
		return (0);
	if (strcmp(cmdStr, ".") && (cmdStr[0] == '.')) {
		cmd = cmdType(userCmd, &cmdStr[1]); // effective command in talking mode,  e.g. ".who"
	} else {
		cmd = cmdType(userCmd, cmdStr); //classify commands
		if ((cmd != U_EOT) && talking)
			cmd = U_FROM;
	}

	// check syntax error
	switch (cmd) {
	case U_USER:
	case U_TALK:
		if (nword != 2) {
			printf("syntax error\n");
			return (-1);
		}
		break;
	case U_FROM:
		break;
	case UNKNOWN:
		printf("syntax error\n");
		return (-1);
	default:
		if (nword < 1) {
			printf("syntax error\n");
			return (-1);
		}
		break;
	}
	// User command processing
	switch (cmd) {
	// Local Commands.
	case U_TALK:
		strcpy(peerList, arg);
		talking = 1;
		setPrompt(peerList);
		return (0);
	case U_EOT: // End of talk (".")
		talking = 0;
		setPrompt(NULL);
		return (0);
	case U_DEBUG:
		debugMode = (debugMode) ? 0 : 1;
		printf("debug mode %s\n", (debugMode) ? "on" : "off");
		setDebug(debugMode);
		return (0);
	case U_HELP:
		printUsage(0);
		return (0);
	case U_DELAY:
		delayMode = (delayMode) ? 0 : 1;
		printf("delay mode %s\n", (delayMode) ? "on" : "off");
		return (0);
		// Build Request Methods
	case U_USER:
		strcpy(userID, arg);
		snprintf(requestMsg, MAXLINE, getFmt(method, T_USER), userID);
		break;
	case U_FROM:
		snprintf(requestMsg, MAXLINE, getFmt(method, T_FROM), userID, peerList,	cmdLine);
		break;
	case U_WHO:
		strcpy(requestMsg, getFmt(method, T_WHO));
		break;
	case U_QUIT:
		strcpy(requestMsg, getFmt(method, T_QUIT));
		break;
		//////////////////////////////////
	case U_SEND:////send <file name> from <sender ID> to <receiver ID>
		strcpy(peerList, temp_to);
		nword = sscanf(cmdLine, "SEND %s FROM %s TO %s", arg, userID, peerList);
		snprintf(requestMsg, MAXLINE, getFmt(method, T_SEND), arg, userID, peerList);//arg->>fileName, userID->> my ID,
		break;
	case U_ACCEPT:////accept <file name> from <sender ID> to <receiver ID>
		strcpy(peerList, temp_to);
		nword = sscanf(cmdLine, "ACCEPT %s FROM %s TO %s", arg, userID, peerList);
		snprintf(requestMsg, MAXLINE, getFmt(method, T_ACCEPT), arg, userID, peerList);//userID=>fileName
		break;
	case U_REJECT:////reject <file name> from <sender ID> to <receiver ID>
		strcpy(peerList, temp_to);
		nword = sscanf(cmdLine, "REJECT %s FROM %s TO %s", arg, userID, peerList);
		snprintf(requestMsg, MAXLINE, getFmt(method, T_REJECT), arg, userID, peerList);//userID=>fileName
		break;
		///////////////////////////////
	case UNKNOWN:
	default:
		printf("Unknown command\n");
		return (-1);
	}

	return (1);
}

/*
 * Parser for response messages
 *  Returns: response message code
 */
int response_parse(char *buf) {
	int code;
	char c;
	char peer[128];
	char *text, *body;
	char *CRLF2, *CRLF;

	if (sscanf(buf, "%d", &code) != 1) {
		printf("response message syntax error: %s", buf);
		return (599);
	}
	// Find textual response, and body message
	for (c = *buf; !isalpha(c); c = *++buf)
		; // skip response code
	text = buf; // Textual response
	CRLF2 = strstr(text, "\r\n\r\n");
	CRLF = strstr(text, "\r\n");
	if ((CRLF2 == NULL) || (CRLF == NULL)) {
		printf("response message syntax error: %s", buf);
		return (599);
	}
	*CRLF2 = '\0';
	if (CRLF != CRLF2) { // response with body
		*CRLF = '\0';
		body = CRLF + 2;
	}

	/*
	 static char *response[] = {
	 "200 OK\r\n\r\n",
	 "210 users list\r\n%s\r\n\r\n",
	 "221 Service closing\r\n\r\n",
	 "230 User logged in\r\n\r\n",
	 "299 Message delivered\r\nFROM %s\r\n\r\n",
	 "500 Syntax error, command unrecognized\r\n\r\n",
	 "530 Not logged in\r\n\r\n",
	 ///////////////////////////////////////
	 "298 File transfer attempt \r\n%s",
	 "227 %s Ready to receive files\r\n%s",
	 "425 Rejected\r\n%s",
	 ////////////////////////////////////
	 };
	 */
	switch (code) {
	case 299://  Message delivered\r\nFROM %s\r\n\r\n
		sscanf(body, "FROM %s", peer);
		body = strstr(body, "\r\n"); // skip FROM line
		printf("%s: %s\n", peer, body + 2); // Print chatting message
		break;
	case 210: // users list\r\n%s\r\n\r\n
		printf("%s\n", body);
		break;
	case 200: // don't print OK message
		break;
	case 298: // File transfer attempt \r\n%s
		printf("TESTING 298\n");
		break;
	case 227: // %s Ready to receive files\r\n%s
		printf("TESTING 227\n");
		break;
	case 425: // 425 Rejected\r\n%s
		printf("TESTING 425\n");
		break;
	default:
		printf("%s\n", text); // Print response message
		break;
	}
	return (code);
}


